package com.neu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.neu.base.AuthContants;
import com.neu.base.PageBean;
import com.neu.base.Result;
import com.neu.base.ServerSentEventsResult;
import com.neu.enums.ServerSentEventsEnum;
import com.neu.entity.*;
import com.neu.entity.DTO.TaskDTO;
import com.neu.entity.security.LoginUser;
import com.neu.handler.ServerSentEventsManager;
import com.neu.mapper.TaskMapper;
import com.neu.service.*;
import com.neu.utils.RedisUtil;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements TaskService {
    @Autowired
    TenantService tenantService;

    @Autowired
    ProjectService projectService;

    @Autowired
    UserService userService;

    @Autowired
    TaskUserService taskUserService;
    @Autowired
    ProjectUserRoleService projectUserRoleService;
    @Autowired
    RoleService roleService;
    @Autowired
    ReviewService1 reviewService;

    @Autowired
    NoticeService noticeService;

    @Autowired
    NoticeUserService noticeUserService;

    @Autowired
    RedisUtil redisUtil;

    @Override
    public PageBean<TaskDTO> pagelist(Integer pageNum, Integer pageSize) {
        Page<Task> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Task> queryWrapper = new LambdaQueryWrapper<>();
        // 查询未删除的任务
        queryWrapper.eq(Task::getDelFlag, "1");

        //根据当前登录用户的权限查询通知
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        List<String> permissions = loginUser.getAuthorityStrings();
        if (!permissions.contains("ROLE_super")) {
            //如果不是超级管理员，只能查看自己参与的任务
            Set<String> projectIds = loginUser.getProjectIdMap().keySet();
            if (!projectIds.isEmpty()) {
                queryWrapper.in(Task::getProjectId, projectIds);
            } else {
                return new PageBean<>(pageNum, pageSize, 0, new ArrayList<>());
            }

        }

        // 查询任务
        Page<Task> taskPage = this.page(page, queryWrapper);

        // 将查询到的任务转换为DTO对象
        List<TaskDTO> taskDTOList = getTaskDTOList(taskPage);

        //将查询到的任务列表封装到PageBean对象中
        PageBean<TaskDTO> pageBean = new PageBean<>(taskPage.getCurrent(), taskPage.getSize(), taskPage.getTotal(), taskDTOList);

        return pageBean;
    }

    private @NotNull List<TaskDTO> getTaskDTOList(Page<Task> taskPage) {
        //先获取任务列表
        List<Task> taskList = taskPage.getRecords();

        List<TaskDTO> taskDTOList = new ArrayList<>();
        for (Task task : taskList) {
            TaskDTO taskDTO = new TaskDTO();
            //将task的属性拷贝到taskDTO
            BeanUtil.copyProperties(task, taskDTO);
            //设置项目名称和租户名称
            String projectId = task.getProjectId();
            Project project = projectService.getById(projectId);
            taskDTO.setProjectName(project.getProjectName());
            String tenantId = project.getTenantId();
            Tenant tenant = tenantService.getById(tenantId);
            taskDTO.setTenantName(tenant.getTenantName());
            taskDTO.setTenantId(tenant.getTenantId());
            //设置前置任务名称
            String preTaskId = task.getPreTask();
            if (StringUtils.hasText(preTaskId)) {
                Task preTask = this.getById(preTaskId);
                taskDTO.setPreTaskName(preTask.getTaskName());
                taskDTO.setPreTaskDetail(preTask);
            }
            //设置负责人姓名
            User user = userService.getById(task.getAssignedTo());
            taskDTO.setAssignedName(user.getUsername());
            //设置参与人列表
            List<TaskUser> taskUserList = taskUserService.list(new LambdaQueryWrapper<TaskUser>().eq(TaskUser::getTaskId, task.getTaskId()));
            List<User> userList = userService.listByIds(taskUserList.stream().map(TaskUser::getUserId).collect(Collectors.toList()));
            taskDTO.setUserList(userList);
            taskDTOList.add(taskDTO);
        }
        return taskDTOList;
    }

    @Override
    public PageBean<TaskDTO> search(Map map) {
        Integer pageNum = (Integer) map.get("pageNum");
        Integer pageSize = (Integer) map.get("pageSize");

        // 获取嵌套的 search Map
        Map<String, Object> searchMap = (Map<String, Object>) map.get("search");
        //{pageNum=1, pageSize=10, search={username=, phone=, status=1, createTimeList=[2024-10-27T16:00:00.000Z, 2024-11-03T16:00:00.000Z], deptIdList=[1842128938393600002, 1842128590274756609]}}

        // 从 search Map 中获取值
        String username = (String) searchMap.get("assignedName");
        String status = (String) searchMap.get("taskStatus");
        String priority = (String) searchMap.get("priority");
        String taskType = (String) searchMap.get("taskType");
        List<String> createTimeList = (List<String>) searchMap.get("createTimeList");
        List<String> tenantIdList = (List<String>) searchMap.get("tenantIdList");
        List<String> projectIdList = (List<String>) searchMap.get("projectList");
        List<String> searchProjectIdList;//最终查询的项目id列表

        List<String> userIdList = new ArrayList<>();
        if (StringUtils.hasText(username)) {
            LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<User>().like(User::getUsername, username);
            userIdList = userService.list(userLambdaQueryWrapper).stream().map(User::getUserId).collect(Collectors.toList());
        }
        //如果 tenantIdList 不为空，同时projectIdList是空的话，就是查询租户下的所有任务
        if (!tenantIdList.isEmpty() && projectIdList.isEmpty()) {
            //查询租户下的所有项目
            List<Project> projectList = projectService.list(new LambdaQueryWrapper<Project>().in(Project::getTenantId, tenantIdList));
            //获取项目id列表
            searchProjectIdList = projectList.stream().map(Project::getProjectId).collect(Collectors.toList());
        } else {
            //其余情况，直接使用projectIdList，直接查询项目下的任务，不用管租户
            searchProjectIdList = projectIdList;
        }

        //把日期字符串转换为日期对象
        LocalDateTime startTime = null;
        LocalDateTime endTime = null;
        if (createTimeList != null && createTimeList.size() == 2) {
            //OffsetDateTime适用于解析带有 "Z" 的日期字符串。
            startTime = OffsetDateTime.parse(createTimeList.get(0), DateTimeFormatter.ISO_OFFSET_DATE_TIME).toLocalDateTime();
            endTime = OffsetDateTime.parse(createTimeList.get(1), DateTimeFormatter.ISO_OFFSET_DATE_TIME).toLocalDateTime();
        }

        LambdaQueryWrapper<Task> queryWrapper = new LambdaQueryWrapper<>();
        //根据当前登录用户的权限查询
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        List<String> permissions = loginUser.getAuthorityStrings();
        if (!permissions.contains("ROLE_super")) {
            //如果不是超级管理员，只能查看自己参与的任务
            Set<String> projectIds = loginUser.getProjectIdMap().keySet();
            if (!projectIds.isEmpty()) {
                queryWrapper.in(Task::getProjectId, projectIds);
            } else {
                return new PageBean<>(pageNum, pageSize, 0, new ArrayList<>());
            }
        }
        Page<Task> page = new Page<>(pageNum, pageSize);

        queryWrapper.in(!userIdList.isEmpty(), Task::getAssignedTo, userIdList)
                .eq(StringUtils.hasText(status), Task::getTaskStatus, status)
                .between(createTimeList != null && createTimeList.size() == 2, Task::getDueDate, startTime, endTime)
                .in(!searchProjectIdList.isEmpty(), Task::getProjectId, searchProjectIdList)
                .eq(StringUtils.hasText(priority), Task::getPriority, priority)
                .eq(StringUtils.hasText(taskType), Task::getTaskType, taskType);

        Page<Task> taskPage = this.page(page, queryWrapper);
        //将查询到的任务转换为DTO对象
        List<TaskDTO> taskDTOList = getTaskDTOList(taskPage);
        //将查询到的任务列表封装到PageBean对象中
        PageBean<TaskDTO> pageBean = new PageBean<>(taskPage.getCurrent(), taskPage.getSize(), taskPage.getTotal(), taskDTOList);
        return pageBean;
    }

    @Override
    public TaskDTO findUserTaskByProjectId(String taskId) {
        Task task = this.getById(taskId);
        TaskDTO taskDTO = new TaskDTO();
        BeanUtil.copyProperties(task, taskDTO);
        List<TaskUser> taskUserList = taskUserService.list(new LambdaQueryWrapper<TaskUser>().eq(TaskUser::getTaskId, task.getTaskId()));
        List<User> userList = userService.listByIds(taskUserList.stream().map(TaskUser::getUserId).collect(Collectors.toList()));
        taskDTO.setUserList(userList);
        return taskDTO;
    }


    @Override
    public Result inviteUserInEdit(TaskDTO taskDTO, Role role, User user) {
        //判断当前用户是否是任务负责人
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (StringUtils.hasText(taskDTO.getAssignedTo()) && !taskDTO.getAssignedTo().equals(loginUser.getUserId())) {
            return Result.error("只有任务负责人才能邀请用户！");
        }

        //Role是被邀请者的角色
        //User是被邀请者
        //TaskDTO是任务

        //需要判断一下是否在task表中插入一条记录 因为调用该方法的是编辑任务的时候，不需要插入一条记录
        //如果taskDTO中的taskId为空，说明是新建任务，需要插入一条记录
        Task task = new Task();
        BeanUtil.copyProperties(taskDTO, task);
        //新增
        if (!StringUtils.hasText(taskDTO.getTaskId())) {
            //检查任务类型，一个项目同种类型的任务只能有一个
            String tasktype = task.getTaskType();
            String projectid = task.getProjectId();
            List<Task> tasks = this.list(new LambdaQueryWrapper<Task>().eq(Task::getTaskType, tasktype).eq(Task::getProjectId, projectid));
            if (!tasks.isEmpty()) {
                return Result.error("该项目的该类型的任务已经存在！");
            }

            //生成一个 32 字符的字符串，不含破折号（-）
            String taskId = UUID.randomUUID().toString().replace("-", "");
            task.setTaskId(taskId);
            task.setAssignedTo(user.getUserId());
            task.setProgress(0);
            task.setCreateTime(LocalDateTime.now());
            task.setCreateId(loginUser.getUserId());
            task.setUpdateTime(LocalDateTime.now());
            task.setUpdateId(loginUser.getUserId());
            task.setDelFlag("1");
            //新增任务的话，将对于的项目状态改为进行中
            String projectId = task.getProjectId();
            Project project = projectService.getById(projectId);
            project.setProjectStatus("1");
            projectService.updateById(project);
            this.save(task);
            if (taskDTO.getTaskType().equals("3")) {
                //先判断是否已经存在评审意见
                List<Review> reviewList = reviewService.list(new LambdaQueryWrapper<Review>().eq(Review::getTaskId, task.getTaskId()).eq(Review::getProjectId, task.getProjectId()));
                if (reviewList.isEmpty()) {
                    Review review = new Review();
                    review.setProjectId(task.getProjectId());
                    review.setTaskId(task.getTaskId());
                    review.setReviewerId(user.getUserId());
                    review.setReviewId(UUID.randomUUID().toString().replace("-", ""));
                    reviewService.save(review);
                }
            }
            //判断邀请的是否是是当前用户
            if (user.getUserId().equals(loginUser.getUserId())) {
               //更新LoginUser的taskidlist
                Map<String,List<String>> projectIdMap = loginUser.getProjectIdMap();
                if(projectIdMap.get(projectId) == null) {
                    projectIdMap.put(projectId, Arrays.asList(role.getRoleId()));
                }else{
                    List<String> roleIds = projectIdMap.get(projectId);
                    Set<String> roleSet = new HashSet<>(roleIds);
                    roleSet.add(role.getRoleId());
                    roleIds = new ArrayList<>(roleSet);
                    projectIdMap.put(projectId,roleIds);
                }
                loginUser.setProjectIdMap(projectIdMap);
                System.out.println("-------------loginUser.getProjectIdMap() = " + loginUser.getProjectIdMap());
                redisUtil.set(AuthContants.REDIS_KEY_AUTH_USER_DETAIL + loginUser.getUsername(), loginUser, 18000);
            }
        }


        //需要在task_user表中插入一条记录
        TaskUser taskUser = new TaskUser();
        taskUser.setUserId(user.getUserId());
        taskUser.setTaskId(task.getTaskId());
        taskUserService.save(taskUser);


        Tenant tenant = tenantService.getById(loginUser.getTenantId());

        //更新notice表
        Notice notice = new Notice();
        notice.setNoticeId(UUID.randomUUID().toString().replace("-", ""));
        notice.setNoticeTitle("项目" + task.getProjectId() + "的 " + task.getTaskName() + " 任务分配通知");
        notice.setNoticeType("1");
        notice.setPriority("1");
        notice.setContent(loginUser.getUsername() + "邀请您成为项目" + task.getProjectId() + "的" + role.getRoleName());
        notice.setTenantId(tenant.getTenantId());
        notice.setProjectId(task.getProjectId());
        notice.setRoleId(role.getRoleId());
        notice.setDelFlag("1");
        notice.setCreateTime(LocalDateTime.now());
        notice.setCreateId(loginUser.getUserId());
        notice.setUpdateTime(LocalDateTime.now());
        notice.setUpdateId(loginUser.getUserId());
        noticeService.save(notice);

        //更新notice_user表
        NoticeUser noticeUser = new NoticeUser();
        noticeUser.setNoticeId(notice.getNoticeId());
        noticeUser.setUserId(user.getUserId());
        noticeUser.setReadFlag("0");
        noticeUser.setStarFlag("0");
        noticeUserService.save(noticeUser);

        ServerSentEventsManager.send(user.getUserId(), new ServerSentEventsResult<>(ServerSentEventsEnum.SSE_NOTICE, notice));
        return Result.success(task.getTaskId());
    }

    @Override
    public boolean removeUserTask(TaskDTO taskDTO, String userId) {
        //先判断是否是负责人，如果是负责人，不能移除
        if (taskDTO.getAssignedTo().equals(userId)) {
            return false;
        }
        LambdaQueryWrapper<TaskUser> taskUserWrapper = new LambdaQueryWrapper();
        taskUserWrapper.eq(TaskUser::getTaskId, taskDTO.getTaskId()).eq(TaskUser::getUserId, userId);

        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Task task = new Task();
        BeanUtil.copyProperties(taskDTO, task);
        //更新notice表
        Notice notice = new Notice();
        notice.setNoticeId(UUID.randomUUID().toString().replace("-", ""));
        notice.setNoticeTitle(task.getTaskName() + "任务取消通知");
        notice.setNoticeType("0");
        notice.setPriority("2");
        notice.setContent(loginUser.getUsername() + "将已将您在项目" + task.getProjectId() + "中的" + task.getTaskName() + "任务取消,请知悉！");
        Tenant tenant = tenantService.getById(projectService.getById(task.getProjectId()).getTenantId());
        notice.setTenantId(tenant.getTenantId());
        notice.setProjectId(task.getProjectId());
        notice.setDelFlag("1");
        notice.setCreateTime(LocalDateTime.now());
        notice.setCreateId(loginUser.getUserId());
        notice.setUpdateTime(LocalDateTime.now());
        notice.setUpdateId(loginUser.getUserId());
        noticeService.save(notice);

        User user = userService.getById(userId);
        NoticeUser noticeUser = new NoticeUser();
        noticeUser.setNoticeId(notice.getNoticeId());
        noticeUser.setUserId(user.getUserId());
        noticeUser.setReadFlag("0");
        noticeUser.setStarFlag("0");
        noticeUserService.save(noticeUser);

        ServerSentEventsManager.send(userId, new ServerSentEventsResult<>(ServerSentEventsEnum.SSE_NOTICE, notice));

        taskUserService.remove(taskUserWrapper);
        return true;
    }

    @Override
    public Result delete(TaskDTO taskDTO) {
        Task task = new Task();
        BeanUtil.copyProperties(taskDTO, task);
        task.setDelFlag("0");
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (!task.getAssignedTo().equals(loginUser.getUserId())) {
            //如果不是负责人，不能删除
            return Result.error("只有负责人才能删除任务！");
        }

        LambdaQueryWrapper<TaskUser> taskUserWrapper = new LambdaQueryWrapper();
        taskUserWrapper.eq(TaskUser::getTaskId, task.getTaskId());
        List<TaskUser> taskUserList = taskUserService.list(taskUserWrapper);

        //更新notice表
        Notice notice = new Notice();
        notice.setNoticeId(UUID.randomUUID().toString().replace("-", ""));
        notice.setNoticeTitle(task.getTaskName() + "任务删除通知");
        notice.setNoticeType("0");
        notice.setPriority("2");
        notice.setContent(loginUser.getUsername() + "将项目" + task.getProjectId() + "的" + task.getTaskName() + "任务删除,请知悉！");
        Tenant tenant = tenantService.getById(projectService.getById(task.getProjectId()).getTenantId());
        notice.setTenantId(tenant.getTenantId());
        notice.setProjectId(task.getProjectId());
        notice.setDelFlag("1");
        notice.setCreateTime(LocalDateTime.now());
        notice.setCreateId(loginUser.getUserId());
        notice.setUpdateTime(LocalDateTime.now());
        notice.setUpdateId(loginUser.getUserId());
        noticeService.save(notice);

        //更新notice_user表
        for (TaskUser taskUser : taskUserList) {
            User user = userService.getById(taskUser.getUserId());
            NoticeUser noticeUser = new NoticeUser();
            noticeUser.setNoticeId(notice.getNoticeId());
            noticeUser.setUserId(user.getUserId());
            noticeUser.setReadFlag("0");
            noticeUser.setStarFlag("0");
            noticeUserService.save(noticeUser);
        }

        List<String> userIdsList = taskUserList.stream().map(TaskUser::getUserId).collect(Collectors.toList());
        ServerSentEventsManager.send(userIdsList, new ServerSentEventsResult<>(ServerSentEventsEnum.SSE_NOTICE, notice));

        //删除任务用户关联表
        taskUserService.remove(taskUserWrapper);
        //删除任务
        this.removeById(task.getTaskId());
        return Result.success();
    }

    @Override
    public List<TaskDTO> getPreTask(TaskDTO taskDTO) {
        String projectId = taskDTO.getProjectId();
        List<Task> taskList = this.list(new LambdaQueryWrapper<Task>().eq(Task::getProjectId, projectId));
        //过滤掉自己
        if (StringUtils.hasText(taskDTO.getTaskId())) {
            taskList = taskList.stream().filter(task -> !task.getTaskId().equals(taskDTO.getTaskId())).collect(Collectors.toList());
        }
        if (taskList.isEmpty()) {
            return new ArrayList<>();
        }
        List<TaskDTO> taskDTOList = new ArrayList<>();
        for (Task task : taskList) {
            TaskDTO taskDTO1 = new TaskDTO();
            BeanUtil.copyProperties(task, taskDTO1);
            taskDTOList.add(taskDTO1);
        }
        return taskDTOList;
    }

    @Override
    public TaskDTO findById(TaskDTO taskDTO) {
        String taskId = taskDTO.getTaskId();
        Task task = this.getById(taskId);
        BeanUtil.copyProperties(task, taskDTO);
        return taskDTO;
    }

    @Override
    public List<Task> sortByUIdAndType(String userId, String taskType, String pageIdx, String pageSize) {
        String aimUserId = userId;
        String aimTaskType = taskType;
        int bias = (Integer.parseInt(pageIdx) - 1) * Integer.parseInt(pageSize);

        if (bias < 0) {
            return new ArrayList<>();
        }

        LambdaQueryWrapper<Task> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(aimTaskType != null, Task::getTaskType, aimTaskType);
        List<Task> afterTaskType = this.list(queryWrapper);
        List<Task> aimTasks = new ArrayList<Task>();
        for (Task t : afterTaskType) {
            List<TaskUser> taskUserList = taskUserService.list(new LambdaQueryWrapper<TaskUser>().eq(TaskUser::getTaskId, t.getTaskId()));
            List<User> users = userService.listByIds(taskUserList.stream().map(TaskUser::getUserId).collect(Collectors.toList()));
            List<String> uIds = new ArrayList<String>();
            for (User u : users) {
                uIds.add(u.getUserId());
            }
            if (uIds.contains(aimUserId)) {
                aimTasks.add(t);
            }
        }

        if (bias >= aimTasks.size()) {
            return new ArrayList<Task>();
        }

        aimTasks = aimTasks.subList(bias, Math.min(bias + Integer.parseInt(pageSize), aimTasks.size()));

        return aimTasks;

    }

    @Override
    public List<Task> allForFp() {
        LambdaQueryWrapper<Task> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Task::getDelFlag, "1")
                .eq(Task::getTaskType, "1");// 查询未删除的项目
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        List<String> permissions = loginUser.getAuthorityStrings();
        if (!permissions.contains("ROLE_super")) {
            //如果不是超级管理员，只能查看自己参与的任务
            Set<String> projectIds = loginUser.getProjectIdMap().keySet();
            if (!projectIds.isEmpty()) {
                queryWrapper.in(Task::getProjectId, projectIds);
            } else {
                return new ArrayList<>();
            }
        }
        return this.list(queryWrapper);
    }

    @Override
    public List<Task> all() {
        LambdaQueryWrapper<Task> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Task::getDelFlag, "1");// 查询未删除的用户

        //根据当前登录用户的权限查询
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        List<String> permissions = loginUser.getAuthorityStrings();
        if (!permissions.contains("ROLE_super")) {
            //如果不是超级管理员，只能查看自己参与的任务
            Set<String> projectIds = loginUser.getProjectIdMap().keySet();
            if (!projectIds.isEmpty()) {
                queryWrapper.in(Task::getProjectId, projectIds);
            } else {
                return new ArrayList<>();
            }
        }
        return this.list(queryWrapper);
    }
}
